<template>
  <el-container>
    <!--侧边栏-->
    <el-aside class="aside-style" width="200px">
      <!--头部-->
      <div class="title clearfix">
        <div id="my-function-library-guide" class="fl">我的函数库</div>
        <i id="create-lib-guide" class="fr el-icon-circle-plus-outline" @click="createLib" />
      </div>
      <!--搜索-->
      <div id="input-guide" class="input-style">
        <el-input
          v-model="search"
          placeholder="输入关键字搜索"
          suffix-icon="el-icon-search"
          size="small"
          @keyup.enter.native="searchKeyword"
        />
      </div>

      <!--渲染函数库-->
      <ul id="my-function-library-exist-guide" ref="wrapper" class="library-ul">
        <li
          v-for="item in libraryList"
          :key="item.libraryName"
          :class="{ active: item.isActive }"
          @click="clickLibrary(item)"
        >
          <p class="library-name text-ellipsis">{{ item.displayLibraryName }}</p>
          <p class="library-desc text-ellipsis">{{ item.desc }}</p>
          <!-- <p class="library-info text-ellipsis">{{ item.state }}</p> -->
        </li>
      </ul>
    </el-aside>

    <!--函数主体-->
    <el-main class="main-style">
      <!--头部-->
      <div class="title clearfix">
        <span>{{ activeLibrary.displayLibraryName }}</span>
        <div class="fr">
          <el-button type="primary" size="mini" @click="buildFun">新增函数</el-button>
          <el-button type="danger" size="mini" @click="deleteLib">删除函数库</el-button>
        </div>
      </div>
      <el-tabs v-model="editableTabsValue">
        <!--函数列表-->
        <el-tab-pane id="function-el-guide" label="函数列表" name="list">
          <m-table
            ref="my_table"
            :data="tableData"
            :total="total"
            :loading="tableLoading"
            @current-change="handleCurrentChange"
          >
            <el-table-column
              prop="functionName"
              label="函数名称"
              width="200"
            />
            <el-table-column
              prop="functionDesc"
              label="功能描述"
            />
            <el-table-column label="操作" width="200">
              <template slot-scope="scope">
                <el-row id="function-edit-guide" class="btn-style">
                  <el-button
                    type="text"
                    @click="contribute(scope.row)"
                  >
                    贡献
                  </el-button>
                  <el-button
                    type="text"
                    @click="pushToEdit(scope.row)"
                  >
                    编辑
                  </el-button>
                  <el-button
                    type="text"
                    @click="updateFun(scope.row)"
                  >
                    修改
                  </el-button>
                  <el-button
                    type="text"
                    class="c-delete"
                    @click="deleteFun(scope.row)"
                  >
                    删除
                  </el-button>
                </el-row>
              </template>
            </el-table-column>
          </m-table>
        </el-tab-pane>

        <!--函数库配置-->
        <el-tab-pane id="function-library-edit-guide" label="函数库配置" name="library">
          <div class="title none-border clearfix">
            <span>基本操作</span>
            <div class="fr">
              <i class="el-icon-edit c-pointer c-primary" @click="updateLib">
                修改函数库配置
              </i>
            </div>
          </div>
          <div class="content">
            <p>
              <span>函数库名称</span>
              <span>{{ activeLibrary.displayLibraryName }}</span>
            </p>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-main>

    <!--贡献函数弹窗-->
    <el-dialog title="基本信息" :visible.sync="showContribute">
      <el-alert
        style="width: 90%; margin: 0 5% 30px 5%;"
        title="请提供您的基本信息，以便于我们审核后联系您"
        type="warning"
      />
      <el-form
        ref="contributeForm"
        :model="contributeForm"
        :rules="contributeRules"
        style="width: 90%; margin: 0 5%;"
      >
        <el-form-item label="姓名" label-width="60px" prop="name">
          <el-input v-model="contributeForm.name" tabindex="1" autocomplete="off" />
        </el-form-item>
        <el-form-item label="电话" label-width="60px" prop="phone">
          <el-input v-model="contributeForm.phone" tabindex="2" autocomplete="off" />
        </el-form-item>
        <el-form-item label="邮箱" label-width="60px" prop="email">
          <el-input v-model="contributeForm.email" tabindex="3" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showContribute = false">取 消</el-button>
        <el-button type="primary" @click="handleContribute">确 定</el-button>
      </div>
    </el-dialog>
  </el-container>
</template>

<script>
/**
 * path: '/functions-library/my',
 * name: 'NewLibrary',
 * title: "我的函数库"
 */
import {
  applyFunctionLibrary,
  deleteFunctionLibrary,
  delFunction,
  getFunctionLibrary,
  getFunctions
} from '@/api/userProjectLibrary';
import { LibraryDenied } from '@/api/userProjectExamine';
import Driver from 'driver.js';
import { mapActions, mapMutations, mapState } from 'vuex';
import { templateFolderName } from '@/config';
import { getObjectUrl } from '@/utils/aliOss';
import { downloadOss } from '@/api/userProject';

export default {
  data() {
    const contributePhoneRule = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('请输入您的电话'));
      } else {
        const landTest = /^0\d{2,3}-\d{7,8}$/.test(value);// 座机号码格式
        const mobileTest = /^1\d{10}$/.test(value);// 手机号码格式
        if (landTest || mobileTest) {
          callback();
        } else {
          return callback(new Error('电话格式不正确'));
        }
      }
    };
    const contributeEmailRule = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('请输入您的邮箱'));
      } else {
        // 邮箱格式 : 以\w起始 中间可以有 -+. 之后@ 之后\w- 之后若干个.\w-
        const reg01 = /^\w+[-+.\w]*@[\w-]+(.[\w-]+)+$/;
        if (!reg01.test(value)) {
          return callback(new Error('邮箱格式不正确'));
        } else {
          callback();
        }
      }
    };
    return {
      search: '',
      libraryList: [],
      originList: [],
      editableTabsValue: 'list',
      tableData: [],
      tableLoading: false,
      total: 0,
      activeLibrary: {},
      lastActiveLibrary: '',
      scroll: 0,
      showContribute: false,
      currentItem: {},
      contributeForm: {
        name: '',
        phone: '',
        email: ''
      },
      contributeRules: {
        name: [{ required: true, message: '请输入您的姓名', trigger: 'blur' }],
        phone: [{ trigger: 'blur', validator: contributePhoneRule }],
        email: [{ trigger: 'blur', validator: contributeEmailRule }]
      }
    };
  },
  computed: {
    ...mapState('user', ['userprefix'])
  },
  created() {
    this.setTitle('函数库及函数');
    this.getLibrary();
  },
  activated() {
    this.setTitle('函数库及函数');
    this.getLibrary();
    this.$refs.wrapper.scrollTop = this.scroll;
  },
  methods: {
    ...mapMutations('functions', ['setTitle', 'setTitle', 'setLibraryAndFunction']),
    ...mapActions('functions', ['updateAliFunction']),
    newUserIntro() {
      if (localStorage.getItem('firstOpenFunctionPage') !== null || this.$store.state.user.lastLogin !== 'firstlogin') {
        return;
      }
      localStorage.setItem('firstOpenFunctionPage', false);

      const driver = new Driver({
        className: 'driver-class',
        animate: true,
        opacity: 0.3,
        padding: 5,
        allowClose: false,
        overlayClickNext: false,
        doneBtnText: '知道了',
        closeBtnText: '关闭',
        nextBtnText: '下一步',
        prevBtnText: '上一步',
        showButtons: true,
        keyboardControl: false,
        scrollIntoViewOptions: {
          block: 'end'
        }
      });

      const steps = [{
        element: '#create-lib-guide',
        popover: {
          title: '新建',
          description: '在此处创建新的函数库',
          position: 'bottom-center'
        }
      }, {
        element: '#my-function-library-exist-guide',
        popover: {
          title: '函数库',
          description: '在此处查看已有的函数库',
          position: 'right'
        }
      }, {
        element: '#function-el-guide',
        popover: {
          title: '函数列表',
          description: '在此处查看当前函数库的函数',
          position: 'top-center'
        }
      }, {
        element: '#function-edit-guide',
        popover: {
          title: '函数',
          description: '对该函数进行贡献，编辑等操作',
          position: 'left'
        }
      }];

      driver.defineSteps(steps);
      driver.reset();
      driver.start();
    },
    getLibrary() {
      this.search = '';
      getFunctionLibrary().then((data) => {
        // 发送后端请求 -> 保存原始数据 -> 将库函数名的用户前缀替换 -> 第一个库函数改为激活状态 -> 取消上次激活的库函数 -> 请求函数信息
        if (data.libraries && data.libraries.length > 0) {
          this.originList = data.libraries;
          this.libraryList = data.libraries;
          this.libraryList.forEach((item) => { // 将库函数名的用户前缀替换
            item.displayLibraryName = item.libraryName.replace(this.userprefix, '');
          });
          // 移除名称为runtime 的库 暂时不用这个功能
          this.libraryList.splice(this.libraryList.findIndex(item => item.displayLibraryName === 'runtime'), 1);
          this.libraryList[0].isActive = true;// 第一个库函数改为激活状态
          this.activeLibrary = this.libraryList[0];
          for (const item of this.libraryList) {
            if (item.libraryName === this.lastActiveLibrary) {
              this.activeLibrary.isActive = false;
              item.isActive = true;
              this.activeLibrary = item;
              break;
            }
          }
          this.getFunctionByLibrary(this.activeLibrary.libraryName);
        } else {
          // 无函数库直接跳转到新建页面
          this.$router.push({ name: 'NewLibrary' });
        }
      });
    },
    clickLibrary(item) {
      this.activeLibrary.isActive = false;
      item.isActive = true;
      this.activeLibrary = item;
      this.getFunctionByLibrary(this.activeLibrary.libraryName);
      // 记住滚动坐标和最近一次点击的函数
      this.scroll = this.$refs.wrapper.scrollTop;
      this.lastActiveLibrary = this.activeLibrary.libraryName;
    },
    createLib() {
      this.$router.push({
        name: 'NewByType',
        params: {
          type: 'createLibrary'
        }
      });
    },
    updateLib() {
      this.setLibraryAndFunction({ // 先保存当前的库和函数
        serviceName: this.activeLibrary.libraryName,
        functionName: ''
      });
      this.$router.push({
        name: 'NewByType',
        params: {
          type: 'updateLibrary',
          options: {
            desc: this.activeLibrary.desc
          }
        }
      });
    },
    deleteLib() {
      if (this.tableData.length > 0) {
        this.$message.error('请检查函数库下面是否还有未删除的函数！');
        return;
      }
      this.$confirm('此操作将永久删除该函数库, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteFunctionLibrary({
          libraryName: this.activeLibrary.libraryName
        }).then((data) => {
          this.getLibrary();
        });
      });
    },
    publishLib() {
      applyFunctionLibrary(this.activeLibrary.libraryName)
        .then(() => {
          this.$message.success('申请成功，请等待管理员审核！');
          this.activeLibrary.state = '申请开放中';
          this.activeLibrary.event = 1;
        });
    },
    closeLib() {
      LibraryDenied([this.activeLibrary.libraryName])
        .then(() => {
          this.$message.success('关闭成功！');
          this.activeLibrary.state = '未开放';
          this.activeLibrary.publishStatus = 0;
        });
    },
    getFunctionByLibrary(libraryName) {
      this.tableLoading = true;
      getFunctions({ libraryName })
        .then((data) => {
          this.tableData = data.functions || [];
          this.total = data.functions?.length || 0;
        })
        .finally((_) => {
          this.tableLoading = false;
          this.newUserIntro();
        });
    },
    buildFun() {
      this.setLibraryAndFunction({ // 先保存当前的库和函数
        serviceName: this.activeLibrary.libraryName,
        functionName: ''
      });
      this.$router.push({
        name: 'NewByType',
        params: {
          type: 'createFunction',
          options: {
          }
        }
      });
    },
    updateFun(row) {
      this.setLibraryAndFunction({ // 先保存当前的库和函数
        serviceName: this.activeLibrary.libraryName,
        functionName: row.functionName
      });
      this.$router.push({
        name: 'NewByType',
        params: {
          type: 'updateFunction',
          options: {
            row
          }
        }
      });
    },
    deleteFun(row) {
      this.$confirm('此操作将永久删除该函数, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const params = {
          libraryName: row.serviceName,
          functionName: row.functionName
        };
        delFunction(params).then(() => {
          this.getFunctionByLibrary(this.activeLibrary.libraryName);
        }).catch((err) => {
          console.log(err);
        });
      });
    },
    pushToEdit(item) {
      console.log(item);
      this.setLibraryAndFunction({ // 先保存当前的库和函数
        serviceName: item.serviceName,
        functionName: item.functionName
      });
      this.$router.push({
        name: 'MyFunction',
        params: {
          timeOut: item.timeOut,
          memorySize: item.memorySize
        }
      });
    },
    searchKeyword() {
      this.libraryList = this.originList.filter((item) => {
        return (
          item.displayLibraryName.includes(this.search) ||
          item.desc.includes(this.search)
        );
      });
    },
    handleCurrentChange(num) {
    },
    contribute(item) {
      var promise = new Promise((resolve, reject) => {
        try {
          const Folder = 'config.yaml';
          const Path = `${templateFolderName}/${item.serviceName}/${item.functionName}/${Folder}`;// ${folder}
          getObjectUrl(Path).then((url) => {
            downloadOss(url).then((resp) => {
              resp.text().then(function(content) {
                var pattern1 = /.""/g;
                var pattern2 = /.''/g;
                var pattern3 = /.\.\.\./g;
                var pattern4 = /.'' ''/g;
                console.log(content.match(pattern1));
                console.log(content.match(pattern2));
                console.log(content.match(pattern3));
                console.log(content.match(pattern4));
                // 正则匹配'' ''识别空格并去掉，避免pattern2空格对单引号匹配的影响
                var targetStr = content;
                if (content.match(pattern4) != null) {
                  targetStr = targetStr.replace(/.'' ''/g, '');
                }
                // 正则匹配""、''、...，确保描述文件中不存在""或''或...，证明描述内容已填充完整
                if (content.match(pattern1) != null) {
                  resolve('存在空值，请检查函数描述是否填写完整！');
                } else if (targetStr.match(pattern2) != null) {
                  // 确认为空内容的''
                  var machindex = targetStr.indexOf(`''`);
                  if (targetStr[machindex - 1] === `:` && targetStr[machindex - 2] === `e` && targetStr[machindex + 2] === `i` && targetStr[machindex + 3] === `n`) {
                    resolve('存在空值，请检查函数描述是否填写完整！');
                  }
                  if (targetStr[machindex - 1] === `:` && targetStr[machindex - 2] === `o` && targetStr[machindex + 2] === null) {
                    resolve('存在空值，请检查函数描述是否填写完整！');
                  }
                } else if (content.match(pattern3) != null) {
                  resolve('存在省略号，请检查函数描述是否填写完整！');
                } else {
                  resolve('success');
                }
                resolve('success');
              });
            });
          });
        } catch (error) {
          this.$message.error('解析错误！请检查是否所有贡献前置步骤已完成！');
          reject(error);
        }
      });
      promise.then((res) => {
        if (res === 'success') {
          this.currentItem = item;
          this.showContribute = true;
        } else {
          this.$message.error(res);
        }
      });
    },
    handleContribute() {
      this.$refs['contributeForm'].validate((valid) => { // 开启校验
        if (!valid) {
          this.$message({
            message: '请检查信息格式',
            type: 'error',
            offset: 40
          });
          return false;
        } else {
          this.showContribute = false;
          const m = this.$message({
            message: '提交中...',
            offset: 40,
            duration: 0
          });

          // 先部署要贡献的函数，然后拉取zip进行备份
          const filePath = JSON.parse(this.currentItem.filePathJson);
          this.$store.commit('functions/setLibraryAndFunction', {
            serviceName: this.currentItem.serviceName,
            functionName: this.currentItem.functionName
          });
          this.$store.commit('functions/setTreeData', filePath);
          this.updateAliFunction({
            usePublicLayers: this.usePublicLayers,
            functionOption: {
              timeOut: this.timeOut,
              memorySize: this.memorySize
            }
          }).then(() => {
            // 部署成功后进行备份
            this.$store.dispatch('functions/contribute', {
              item: this.currentItem,
              form: this.contributeForm
            }).then(() => {
              m.close();
              this.$message({
                message: '提交成功！我们会在审核后尽快给您反馈结果！',
                type: 'success',
                offset: 40
              });
            }).catch((e) => {
              m.close();
              console.error(e);
            });
          });
        }
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.aside-style {
  height: calc(100vh - 100px);
  background: #fbfbfb;
  overflow: hidden;

  .title {
    height: 50px;
    line-height: 50px;
    padding: 0 20px;
    background: #f7f7f7;

    i {
      font-size: 20px;
      line-height: 50px;
      cursor: pointer;
    }
  }

  .input-style {
    padding: 10px;
  }

  .library-ul {
    padding: 0 10px;
    height: calc(100% - 130px);
    overflow-y: auto;
    overflow-x: hidden;

    li {
      list-style: none;
      min-height: 50px;
      padding: 0 10px;
      border-bottom: 1px solid #e5e5e5;
      cursor: pointer;

      &.active {
        border: 1px solid #0070cc;
      }

      .library-name {
        color: #333;
      }

      .library-desc {
        font-size: 12px;
        color: #555;
      }

      .library-info {
        font-size: 12px;
        text-align: right;
        color: #555;
      }
    }
  }
}

.main-style {
  height: calc(100vh - 100px);
  overflow: hidden;
  padding: 10px;

  .title {
    height: 50px;
    line-height: 50px;
    padding: 0 20px;
    border-bottom: 1px solid #e5e5e5;
    margin-bottom: 10px;

    &.none-border {
      border: none;
    }
  }

  .content {
    p {
      padding: 10px 30px;

      span {
        margin-right: 50px;
      }
    }
  }
}
</style>
